/* file.js 文件资源管理模块 by zds 2018-10-05 */
// "sharp": "^0.30.0", npm安装
const fs = require('fs');
const rootPath = require('app-root-path');
const makeDir = require('make-dir');
const config = require("../../config/config")
const sharp = require('sharp');
const Path = require('path')
// 文件工具类
const sfile = {
	uploadRoot: '/temporary',	// 上传文件根目录
	allowAccessTo: ['file'], // 允许访问目录
	webRoot: rootPath + '/public',	// web项目路径
	istype: ['png', 'jpeg', 'web', 'gif'],	//允许上传文件类型
	delay: 1000 * 60 * 30,	// 文件保存时间
	imageSize: 400,		// 保存图片大小
	quality: 1000,		// 图片压缩质量，100表示最好,1000表示不压缩

	// 获取扩展名
	getExtension: function (filename) {
		if (filename) {
			let p = filename.lastIndexOf('.');
			if (p != -1)
				return filename.substring(p + 1);
		}
	},
	// 自动重命名
	autoFilename: function (source, dir, filename) {
		let catalog = this.webRoot + dir + '/';
		// 添加扩展名
		let ext = this.getExtension(source);
		if (!ext)
			ext = "";
		else
			ext = "." + ext;

		// 如果存在重名，则添加序号
		let n = 1;
		let rename = filename;
		while (fs.existsSync(catalog + rename + ext)) {
			// console.log("文件已存在：" + rename + ext);
			rename = filename + "-" + n;
			n++;
		}
		return rename + ext;
	},
	// 是否可以访问目录
	accessDir: function (dir) {
		return this.allowAccessTo.indexOf(dir) != -1;
	},
	// 判断文件是否为图片
	isImage: function (name) {
		const extArray = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
		let ext = this.getExtension(name);
		if (!ext)
			return false;
		return extArray.indexOf(ext) != -1;
	},
	// 创建缩略图
	saveImage: function (dir, name, size) {
		if (!dir) return null;
		if (typeof name == 'number') {
			size = name;
			name = '';
		}
		let source;
		if (!name) {
			source = dir;
			let p = dir.lastIndexOf('/');
			if (p == -1 || p == 0) {
				name = dir;
				dir = '/';
			} else {
				name = dir.substring(p + 1);
				dir = dir.substring(0, p);
			}
		} else {
			source = dir + '/' + name;
		}
		// 检查源文件是否存在
		let pathname = this.webRoot + source;
		if (!fs.existsSync(pathname)) {
			return null;
		}
		let img = images(pathname);
		let width = img.width();
		let height = img.height();
		// console.log('width=' + width + ', height=' + height);

		// 限制图片大小
		if (!size) size = this.imageSize;
		if (width < height) {
			width = Math.round(width * size / height);
			height = size;
		} else {
			width = size;
			height = Math.round(height * size / width)
		}
		// console.log('width=' + width + ', height=' + height);
		img.resize(width);
		let catalog = this.webRoot + this.thumbDir + dir;
		if (!fs.existsSync(catalog)) {
			makeDir.sync(catalog);
		}
		img.save(catalog + '/' + name, { quality: this.quality });
		return this.thumbDir + dir + '/' + name;
	},
	// 给文件夹中的所有图片创建缩略图
	build: function (dir, size) {
		if (!dir) return 0;
		let catalog = sfile.webRoot + dir;
		// 检查目录是否存在
		if (!fs.existsSync(catalog)) {
			return 0;
		}
		// 如果 dir 是文件夹
		let stat = fs.statSync(catalog);
		if (stat.isDirectory) {
			let sum = 0;
			for (let fname of fs.readdirSync(catalog)) {
				stat = fs.statSync(catalog + '/' + fname);
				if (stat.isFile() && this.isImage(fname)) {
					this.saveImage(dir, fname, size);
					sum++;
				}
			}
			return sum;
		}
		// 如果 dir 是文件
		if (this.isImage(dir)) {
			this.saveImage(dir, size);
			return 1;
		}
		return 0;
	},
	// 延时删除文件
	delayDelete: function (path) {
		if (!path) return;
		setTimeout(function () {
			// 检查源文件是否存在
			if (!fs.existsSync(path)) {
				return;
			}
			fs.unlinkSync(path);
		}, this.delay);
	},
	// 压缩并删除原文件
	compressAndDelete(oldPath, newPath) {
		// 读取oldPath转为buffer
		const buffer = fs.readFileSync(oldPath);
		// 压缩图片
		return sharp(buffer)
			.toFormat(sharp.format.jpeg) // 转换为 JPEG 格式
			.jpeg({ quality: sfile.quality }) // 设置 JPEG 压缩质量为 80%
			.toFile(newPath, (err, info) => {
				if (err) {
					console.log(err);
					return;
				}
				fs.unlinkSync(oldPath);
			}); // 输出到新路径
	}
}
module.exports = {
	// 列出 dir 目录中的文件
	list: async (ctx, next) => {
		let dir = ctx.request.query.dir || '';
		// console.log('Find dir: ' + dir);
		// 访问用户根目录
		if (!dir || dir == '/') {
			dir = sfile.uploadRoot;
		} else if (dir.charAt(dir.length - 1) == '/') {
			// 去掉末尾的分隔符
			dir = dir.substring(0, dir.length - 1);
		}
		// 检查访问权限
		if (!sfile.accessDir(dir)) {
			return ctx.body = { code: 1002, message: '没有文件夹权限: ' + dir };
		}
		let catalog = sfile.webRoot + '/' + dir;
		console.log('dir :>> ', dir);
		console.log('catalog :>> ', catalog);
		// 检查目录是否存在
		if (!fs.existsSync(catalog)) {
			return ctx.body = { code: 1004, message: '目录不存在: ' + dir };
		}
		let type = ctx.request.query.type;
		let data = [];
		for (let fname of fs.readdirSync(catalog)) {
			var stat = fs.statSync(catalog + '/' + fname);
			//console.log(stat);
			if (stat.isDirectory()) {
				if (type != 'file')
					data.push({ name: fname, changed: stat.mtime });
			} else {
				if (type != 'dir')
					data.push({ name: fname, size: stat.size, changed: stat.mtime });
			}
		}
		return ctx.body = { code: 0, data };
	},
	// POST 上传文件到临时存放目录
	upload: async (ctx, next) => {
		// 拿到files对象的所有key
		let files = Object.keys(ctx.request.files);
		// 文件对象
		let uploadFiles = [];
		files.forEach(function (key) {
			uploadFiles.push(ctx.request.files[key]);
		});
		let path = []
		if (uploadFiles.length == 0)
			return ctx.body = { code: 1004, message: '没有文件上传' };
		if (!(uploadFiles instanceof Array)) {
			uploadFiles = [uploadFiles];
		}
		uploadFiles.forEach(file => {
			if (file instanceof Array) {
				file.forEach(f => {
					let newNmae = sfile.quality != 1000 ? 'ys' + f.newFilename : f.newFilename
					let oldPath = Path.join(__dirname, '../../public/temporary/' + f.newFilename)
					let newPath = Path.join(__dirname, '../../public/temporary/' + newNmae) //压缩后文件路径
					if (sfile.quality != 1000) {
						// 压缩图片并删除原图片
						sfile.compressAndDelete(oldPath, newPath)
					}
					// 过时删除文件
					sfile.delayDelete(newPath);
					path.push(sfile.uploadRoot + '/' + newNmae);
				})
			}
			else {
				let newNmae = sfile.quality != 1000 ? 'ys' + file.newFilename : file.newFilename
				let oldPath = Path.join(__dirname, '../../public/temporary/' + file.newFilename)
				let newPath = Path.join(__dirname, '../../public/temporary/' + newNmae) //压缩后文件路径
				if (sfile.quality != 1000) {
					// 压缩图片并删除原图片
					sfile.compressAndDelete(oldPath, newPath)
				}
				// 过时删除文件
				sfile.delayDelete(newPath);
				path.push(sfile.uploadRoot + '/' + newNmae);
			}

		})
		// if(ctx.passport.id == 0)
		// 	return ctx.body = {code: 1006, message: '游客不能上传文件'};
		return  ctx.body = {
			code:200,
			data:{
				path,
				time:sfile.delay/1000/60/60
			}
		}
		return ctx.body = ctx.msg.success.call(ctx, {
			path,
			time: sfile.delay / 1000 / 60 / 60
		})
	},
	// 删除 dir 目录下的多个文件
	remove: async (ctx, next) => {
		let dir = ctx.request.query.dir;
		let name = ctx.request.query.name;
		if (!dir || !name)
			return ctx.body = { code: 1010, message: '目录和文件名不能为空' };
		if (!sfile.accessDir(dir))
			return ctx.body = { code: 1002, message: '没有文件夹权限: ' + dir };
		// console.log('Delete dir: ' + dir + ', name: ' + name);

		let names = name.split(/\s*\,\s*/);
		let catalog = sfile.webRoot + dir;
		let thumbDir = sfile.webRoot + sfile.thumbDir + dir;
		let data = [];
		for (let item of names) {
			let pathname = catalog + '/' + item;
			if (fs.existsSync(pathname)) {
				fs.unlinkSync(pathname);
				// 删除缩略图
				let thumbPath = thumbDir + '/' + item;
				if (fs.existsSync(thumbPath))
					fs.unlinkSync(thumbPath);
				data.push(item);
			}
		}
		// 返回删除的文件名列表
		return ctx.body = { code: 0, data };
	},

	// 创建文件夹
	mkdir: async (ctx, next) => {
		let dir = ctx.request.query.dir;
		// console.log('Create dir: ' + dir);
		if (!dir)
			return ctx.body = { code: 1010, message: '目录不能为空' };
		if (!sfile.accessDir(dir))
			return ctx.body = { code: 1002, message: '没有文件夹权限: ' + dir };

		let catalog = sfile.webRoot + dir;
		makeDir.sync(catalog);
		return ctx.body = { code: 0, data: dir };
	},

	// 删除空文件夹
	rmdir: async (ctx, next) => {
		let dir = ctx.request.query.dir;
		// console.log('Delete dir: ' + dir);
		if (!dir)
			return ctx.body = { code: 1010, message: '目录不能为空' };
		if (!sfile.accessDir(dir))
			return ctx.body = { code: 1002, message: '没有文件夹权限: ' + dir };

		let catalog = sfile.webRoot + dir;
		fs.rmdirSync(catalog);
		return ctx.body = { code: 0, data: dir };
	},

	// 创建缩略图
	build: async (ctx, next) => {
		let dir = ctx.request.query.dir;
		// console.log('Build dir: ' + dir);
		if (!dir)
			return ctx.body = { code: 1010, message: '目录不能为空' };
		if (!sfile.accessDir(dir))
			return ctx.body = { code: 1002, message: '没有文件夹权限: ' + dir };
		let size = ctx.request.query.size;
		if (size)
			size = ctx.jpart.parseInt(size);
		let name = ctx.request.query.name;
		let sum = 0;
		if (!name) {
			// 创建当前目录的缩略图
			sum = sfile.build(dir, size);
		} else {
			// 创建文件或文件夹的缩略图
			let names = name.split(/\s*\,\s*/);
			for (let item of names) {
				sum += sfile.build(dir + '/' + item, size);
			}
		}
		return ctx.body = { code: 0, data: sum };
	}

}

